#include "ClientMgr.h"

#include "ClientMsg.h"
#include "Log.h"


#include <iostream>


#define WAIT_INPUT_STRING ">"


#ifdef _WIN32
#include <windows.h>
#include <conio.h>
#else
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>

//https://blog.csdn.net/wainiwann/article/details/38978039
int _kbhit(void)
{
    struct termios oldt, newt;
    int ch;
    int oldf;

    tcgetattr(STDIN_FILENO, &oldt);
    newt = oldt;
    newt.c_lflag &= ~(ICANON | ECHO);
    tcsetattr(STDIN_FILENO, TCSANOW, &newt);
    oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
    fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);

    ch = getchar();

    tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
    fcntl(STDIN_FILENO, F_SETFL, oldf);

    if (ch != EOF)
    {
        ungetc(ch, stdin);
        return 1;
    }

    return 0;
}
#endif

using std::cout;
using std::endl;



CmdHandleLoader ayCmdHandle[] =
{
    {"help", "show all cmd", &CClientMgr::HandleHelp, &CClientMgr::Instance() },
    {"login", "[name] login to server", &CClientMgr::HandleLogin, &CClientMgr::Instance() },
};



CClientMgr::CClientMgr()
{
}


CClientMgr::~CClientMgr()
{
}

bool CClientMgr::Init()
{
    m_mapCmdHandles.clear();

    int iCount = sizeof(ayCmdHandle) / sizeof(CmdHandleLoader);
    for (int i = 0; i < iCount; ++i)
    {
        if (!m_mapCmdHandles.insert(pair<string, CmdHandleLoader>(ayCmdHandle[i].stCmd, ayCmdHandle[i])).second)
        {
            LOG_ERR("handle insert fail.cmd:%s", ayCmdHandle[i].stCmd.c_str());
        }
    }
	return true;
}

void CClientMgr::SetSocket(int iSocket)
{
	m_iSocket = iSocket;
}

int CClientMgr::Handle(const string &sCmd, vector<string> &vecParam)
{
    HandleMap::iterator mapHandleIt = m_mapCmdHandles.find(sCmd);

    if (mapHandleIt != m_mapCmdHandles.end())
    {
        if (mapHandleIt->second.pHandleClass != NULL && mapHandleIt->second.pfCmdHandle != NULL)
        {
            return (mapHandleIt->second.pHandleClass->*mapHandleIt->second.pfCmdHandle)(sCmd, vecParam);
        }
    }
    else
    {
        LOG_ERR("not find handle. cmd:%s", sCmd.c_str());
        return -1;
    }
	return 0;
}


int CClientMgr::HandleHelp(const string &sCmd, vector<string> &vecParam)
{
    int iIndex = 1;
    for (HandleMap::iterator mapHandleIt = m_mapCmdHandles.begin(); mapHandleIt != m_mapCmdHandles.end(); ++mapHandleIt)
    {
        cout << iIndex << "." << mapHandleIt->second.stCmd << ":" << mapHandleIt->second.stDesc << endl;
        ++iIndex;
    }

    return 0;
}


int CClientMgr::HandleLogin(const string &sCmd, vector<string> &vecParam)
{
    if (vecParam.size() < 1)
    {
        LOG_ERR("this cmd need more param. cmd:%s, param count:%d",sCmd.c_str(), (int)vecParam.size());
        return -1;
    }

    string stName = vecParam[0];

    cs::LoginReq csLoginReq;
    csLoginReq.set_name(stName);

    //LOG_DBG("login:%s", csLoginReq.DebugString().c_str());
    CClientMsg::Instance().SendMsg(comm::ENM_MODULE_LOGIN, cs::ENM_LOGIN_REQ,csLoginReq,HandleLoginRes);

    return 0;
}


int CClientMgr::HandleLoginRes(const string &pbLoginRes)
{
    return 0;
}

void CClientMgr::ShowWelcomeToConsole()
{
    cout << endl;
    cout << "welcome to lost world" << endl;
    cout << "please input cmd:" << endl;
    cout << WAIT_INPUT_STRING;
}

bool CClientMgr::CheckInputFromConsole()
{
    if (_kbhit())
    {
        char cGetChat = _getch();
        switch (cGetChat)
        {
        case 8://退格键
            if (m_stConsoleInputBuff.size() > 0)
            {
                m_stConsoleInputBuff.pop_back();
                //退格,用空格清除已显示字符,再退格 
                cout << cGetChat << ' ' << cGetChat;
            }
            break;
        case 13://回车键
            if (m_stConsoleInputBuff.size() > 0)
            {
                cout << endl;
                return true;
            }
            break;
        default:
            if (cGetChat >= 'A' && cGetChat <= 'Z'
                || cGetChat >= 'a' && cGetChat <= 'z'
                || cGetChat >= '0' && cGetChat <= '9'
                || cGetChat == '_'
                || cGetChat == ' ')
            {
                m_stConsoleInputBuff.push_back(cGetChat);
                cout << cGetChat;
            }
        }
    }
    return false;
}

const string & CClientMgr::GetInputFromConsole()
{
    return m_stConsoleInputBuff;
}

void CClientMgr::ClearInputFromConsole()
{
    m_stConsoleInputBuff.clear();
}
